if(!window.mc){
	window.mc = function(){};
}
mc.init = function(url,m,f,t){
	mc.delay = 5;
	mc.timeout = 60;
	mc.reconnect_progress = false;
	mc.reconnect_try = 0;
	mc.url = url;
	mc.rid = 1000;
	mc.sid = "";
	mc.cbs = {};
	mc.last_check = false;
	mc.target = $("#"+m);
	mc.topic = $("#"+t);
	mc.source = $("#"+f).submit(mc.submit);
	mc.txt = $("#"+ f +' input[type="text"]');
	mc.target.click(mc.click);
	mc.max_size = 500000;
}
mc.start = function(login,pass,chanel){
	mc.login = login;
	mc.pass = pass;
	mc.def_chanel = chanel;
	mc.restart();
}
mc.restart = function(){
	mc.SendMessage({"cmd":"login","login":mc.login,"pass":mc.pass},mc.login_handler);
}
mc.input_replace = function(found,cmd,list){
	mc.inserted = true;
	var ary = list.split(",");
	var p = false;
	for(var i = 0; i< ary.length; i++){
		ary[i] = ary[i].replace(/^\s+/,"").replace(/\s+$/,"");
		if(ary[i] == mc.input_login){
			p = true;
			break;
		}
	}
	if(!p){
		ary.push(mc.input_login);
	}
	return cmd + "[" + ary.join(",") + "]";
}
mc.click = function(e){
	var t = $(e.target);
	if(t.is("a")){
		if(t.hasClass("ext")){
			return true;
		}
		if(t.hasClass("cmd")){
			mc.submit(null,t.html());
			return false;
		}
		if(t.hasClass("inp")){
			mc.write_text(t.html());
			return false;
		}
	}else if(t.is("span") && t.hasClass("login")){
		var v = mc.txt.val();
		mc.input_login = t.html();
		mc.inserted = false;
		var nv = v.replace(/(private|to|для|лично)\s*\[([\w\sа-яА-Я,]+)\]/,mc.input_replace);
		if(!mc.inserted){
			if(t.hasClass("priv")){
				nv = "лично[";
			}else{
				nv = "для[";
			}
			nv += mc.input_login +"] " + v;
		}
		mc.write_text(nv);
	}else if(t.is("img") && t.hasClass("sm")){
		var f = t.attr("src").match(/\/(\w+)\.gif/);
		if(f){
			mc.txt.val(mc.txt.focus().caret().replace(":" + f[1] + ":"));
		}
	}
	return false;
}
mc.parse_command = function(msg){
	var m = msg.match(/^\s*[\/\.]([\wа-яА-Я]+)(?:\s+([\wа-яА-Я]+))?(?:\s+([\wа-яА-Я]+))?(?:\s+([\wа-яА-Я]+))?/);
	if(m){
		switch(m[1]){
			case "help":
			case "рудз":
				return ""+
				"Доступные команды:<br>"+
				"<a class=cmd href=\"#\">/who</a> - мой ник<br>"+
				"<a class=cmd href=\"#\">/list</a> - список присутствующих<br>"+
				"<a class=cmd href=\"#\">/exit</a> - выход<br>" +
				"<a class=cmd href=\"#\">/clear</a> - очистка сообщений<br>" +
				"<a class=cmd href=\"#\">/reload</a> - перезаход<br>" +
				"<a class=inp href=\"#\">/rename</a> новый_логин - смена логина<br>" +
				"<a class=inp href=\"#\">/setpass</a> новый_пароль - установка пароля<br>" +
				"Личное сообщение: <a class=inp href=\"#\">private[ник]</a> сообщение<br>"+
				"Личное сообщение: <a class=inp href=\"#\">лично[ник]</a> сообщение<br>"+
				"Адресное сообщение: <a class=inp href=\"#\">to[ник]</a> сообщение<br>"+
				"Адресное сообщение: <a class=inp href=\"#\">для[ник]</a> сообщение<br>";
			case "who":
			case "црщ":
				return "Ваш логин: <b>"+mc.login+"</b>";
			case "list":
			case "дшые":
				return {"cmd":"list","chanel":mc.def_chanel};
			case "rename":
			case "кутфьу":
				var nl = "";
				if(m[2]){
					nl += m[2];
				}
				if(m[3]){
					nl += m[3];
				}
				if(m[4]){
					nl += m[4];
				}
				return {"cmd":"chlog","newlogin":nl};
			case "setpass":
			case "ыуезфыы":
				if(!mc.temporary){
					return "это доступно только для временных логинов";
				}
				var np = "";
				if(m[2]){
					np += m[2];
				}
				if(m[3]){
					np += m[3];
				}
				if(m[4]){
					np += m[4];
				}
				return {"cmd":"setpass","newpass":np};
			case "reload":
			case "кудщфв":
				var c = $.toJSON({"l":mc.login,"p":mc.pass});
				$.cookie("reload",c);
				top.location.reload();
				return "reloading..."
			case "exit":
			case "учше":
				$.cookie("reload",null);
				$.cookie("keep",null);
				top.location.reload();
				return "exiting..."
			case "clear":
			case "сдуфк":
				var api = mc.target.data().jsp;
				api.getContentPane().html("");
				api.reinitialise();
				return "теперь чисто";
			default:
				if(mc.ext && mc.ext.input){
					return mc.ext.input(m);
				}
		}
	}
	mc.parse_error = true;
	return undefined;
}
mc.parse_message = function(msg){
	var r = msg.match(/(?:private|лично)\s*\[([\w\s,а-яА-Я]+)\](.*)/);
	if(r){
		var list = r[1].split(",");
		var f = false;
		for(var i = 0; i< list.length; i++){
			list[i] = list[i].replace(/^\s+/,"").replace(/\s+$/,"");
			if(list[i] == mc.login){
				f = true;
				break;
			}
		}
		if(!f){
			list.push(mc.login);
		}
		if(r[2] && r[2].match(/\S/)){
			return {"cmd":"private","text": msg,"to":list};
		}else{
			return undefined;
		}
	}else if(msg.match(/(?:to|для)\s*\[[\w\s,а-яА-Я]+\]\s*$/)){
		return undefined;
	}else{
		return {"cmd": "message","text": msg};
	}
}
mc.parse = function(msg){
	if(msg.match(/^\s*[\/\.]/)){
		return mc.parse_command(msg);
	}else{
		return mc.parse_message(msg);
	}
}
mc.html = function(found,chr){
	switch(chr){
		case '<':
			return "&lt;";
		case '>':
			return "&gt;";
		case '&':
			return "&amp;";
		default:
			return chr;
	}
}
mc.submit = function(obj,force) {
	try {
		var str;
		if(force){
			str = force;
		}else{
			str = mc.txt.val();
		}
		if(str != ""){
			mc.parse_error = false;
			var msg = mc.parse(str);
			if(msg){
				if(typeof(msg) == "string"){
					mc.console(msg);
					mc.write_text();
				}else{
					mc.SendMessage(msg,mc.write_text);
				}
			}else if(mc.parse_error){
				mc.console("плохая строка: " + str.replace(/([<>&])/g,mc.html));
			}
		}
	}catch(msg) {
		alert("err:"+msg);
	}
	return false;
}
mc.write_text = function(obj,force){
	if(!force){
		force = "";
	}
	var l = force.length;
	mc.txt.val(force).focus().caret(l,l);
}
mc.restart_after = function(delay){
	if(!mc.reconnect_progress){
		if(mc.reconnect_try == 0){
			mc.console("reconnect...");
		}else if(mc.reconnect_try > 10){
			mc.console("server unreacheble... stoped.");
			return false;
		}
		mc.reconnect_try++;
		mc.reconnect_progress = true;
		mc.target.delay(delay).queue(function(){
			mc.restart();
			mc.target.dequeue();
			mc.reconnect_progress = false;
		});
	}
	return false;
}
mc.SendMessage = function(msg,callback){
	if(!msg.rid){
		msg.rid = mc.rid++;
	}
	msg.sid = mc.sid;
	if(!msg.chanel){
		msg.chanel = mc.def_chanel;
	}
	if(callback){
		mc.cbs[msg.rid] = callback;
	}
	var cmd = msg.cmd;
	delete msg.cmd;
	var nr = msg.rid;
	$.ajax({
		url: mc.url+cmd,
		type: "POST",
		dataType: "json",
		success: mc.read_handler,
		error: function(jqXHR, textStatus, errorThrown){mc.error_handler(nr,jqXHR, textStatus, errorThrown)},
		timeout: mc.timeout*1000,
		processData: false,
		contentType: "text/x-javascript",
		data: $.toJSON(msg)
	});
}
mc._message = function(t){
	var api = mc.target.data().jsp;
	
	api.getContentPane().append(t);
	var ns = api.getContentPane().html();
	if(ns.length > mc.max_size){
		var str = ns.substring(Math.floor(mc.max_size/3));
		var i = str.indexOf("<div");
		str = str.substring(i);
		api.getContentPane().html(str);
	}
	api.reinitialise();
	api.scrollTo(0,10000);
}
mc.format_message = function(t){
	return mc._message(mc._format_message(t));
}
mc.console = function(msg){
	var str = '<div class="msg inn">' + msg + '</div>';
	mc._message(str);
}
mc._format_message = function(msg){
	mc.crl = "login ";
	if(msg.private){
		mc.crl += "priv";
	}else{
		mc.crl += "comm";
	}
	mc.crl = '"' + mc.crl + '"';
	mc.self = false;
	var rt = msg.text.replace(/\[([\w\s,а-яА-Я]+)\]/g,mc.format_replace);

	var d = "msg";
	if(msg.from && msg.from == mc.login){
		d += " self";
	}else if(mc.self){
		d += " to";
	}else{
		d += " com";
	}
	if(msg.mclass){
		d += " " + msg.mclass;
	}
	d= '"' + d + '"';
	var str = "<div class=" + d + ">";
	str += "<span class=time>" + msg.ts + "</span>";
	if(msg.from){
		str += " [<span class=" + mc.crl + ">" + msg.from + "</span>]";
	}
	if(mc.smiles){
		rt = mc.smiles(rt);
	}
	str += ": " + rt +"</div>";
	return str;
}
mc.format_replace = function(f,list){
	var all = list.split(",");
	var ary = [];
	for(var i = 0;i < all.length;i++){
		all[i] = all[i].replace(/^\s+/,"").replace(/\s+$/,"");
		ary.push("<span class=" + mc.crl + ">" + all[i] + "</span>");
		if(all[i] == mc.login){
			mc.self = true;
		}
	}
	return " [" + ary.join(",") + "]";
}
mc.read_handler = function(data){
	try{
	var rid = data.rid;
	
	if(rid && mc.cbs[rid]){
		mc.cbs[rid].call(null,data);
		mc.cbs[rid] = undefined;
	}
	if(data.type && data.type == "list"){
		data.list.sort(function(a,b){return a.ats - b.ats});
		for(var i = 0; i < data.list.length; i++){
			mc.process_response(data.list[i]);
		}
	}else{
		mc.process_response(data);
	}
	}catch(e){
		mc.console("Err: " + e);
	}
}
mc.process_response = function(data){
	switch(data.type){
		case "notice":
			switch(data.param1){
				case "welcome" :
					mc.console("Добро пожаловать в чат, <b>" + mc.login + "</b>. Помощь: <a class=cmd href=\"#\">/help</a>");
					if(data.param2){
						mc.temporary = true;
						mc.console("Логин временный.");
						mc.console("Что бы сделать его постоянным требуется установить пароль командой <a class=inp href=\"#\">/setpass</a> новый_пароль");
						mc.console("сменить логин можно командой <a class=inp href=\"#\">/rename</a> новый_логин");
					}
					break;
				case "join":
					data.text = "Подключился [" + data.param2 + "].";
					mc.format_message(data);
					break;
				case "rejoin":
					data.text = "[" + data.param2 + "] сменил логин на [" + data.param3 + "].";
					mc.format_message(data);
					$.cookie("reload",null);
					$.cookie("keep",null);
					break;
				case "leave":
					data.text = "Отключился [" + data.param2 + "].";
					mc.format_message(data);
					break;
				case "list":
					data.text = "Список: " + data.param2 + ".";
					mc.format_message(data);
					break;
				case "newlogin":
					mc.login = data.param2;
					mc.console("Новый логин: <b>" + data.param2 + "</b>.");
					break;
				case "newpass":
					mc.temporary = false;
					mc.pass = data.param2;
					mc.console("Новый пароль: <b>" + data.param2 + "</b>.");
					$.cookie("reload",null);
					$.cookie("keep",null);
					break;
				case "topic":
					mc.topic.html(data.param2);
					break;
				case "exec":
					eval(data.param2);
					break;
			}
			break;
		case "response":
			if(data.error){
				mc.console("Error: " + data.error + " " + data.text);
			}
			break;
		case "message":
			mc.format_message(data);
			break;
		default:
			if(mc.ext && mc.ext.response){
				mc.ext.response(data);
			}
	}
}
mc.error_handler = function(rid,jqXHR, textStatus, errorThrown){
	if(rid && mc.cbs[rid]){
		mc.cbs[rid] = undefined;
	}
	if(rid && rid == mc.last_check && errorThrown == "timeout"){
		mc.check_handler();
	}else{
		mc.restart_after(mc.delay*1000);
	}
}
mc.login_handler = function(data){
	if(mc.reconnect_try > 0){
		mc.reconnect_try = 0;
	}
	if(data.sid){
		mc.sid = data.sid;
	}
	if(data.error){
		alert("error:" + data.text);
		return;
	}
	if($.cookie("keep")){
		$.cookie("reload",$.toJSON({"l":mc.login,"p":mc.pass}),{"expires":365});
	}
	mc.SendMessage({"cmd":"join","chanel":mc.def_chanel},mc.check_handler);
}
mc.check_handler = function(data){
	if(data && data.error){
		alert("error:" + data.text);
		return;
	}
	var nr = mc.rid++;
	mc.last_check = nr;
	mc.SendMessage({"cmd":"check","rid":nr},mc.check_handler);
}
